package xyz.haijin.zt.core.util;


import xyz.haijin.zt.core.annotation.Column;
import xyz.haijin.zt.core.annotation.ID;
import xyz.haijin.zt.core.db.DbConnection;

import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

/**
 * @author haijin
 */
public final class BaseUtil {

    /**
     * 执行sql语句
     * @param sql
     * @param connection
     * @param beanClass
     * @param fieldList
     * @param fieldMap
     * @param <T>
     * @return
     */
    public static<T>  List<T> findBySql(String sql, DbConnection connection, Class<T> beanClass, List<String> fieldList, Map<String, Field> fieldMap) {
        ResultSet resultSet = connection.query(sql);
        List<T> list = new ArrayList<T>();
        if(resultSet != null) {
            try {
                while(resultSet.next()){
                    T object = generateObject(beanClass,fieldList,fieldMap,resultSet);
                    list.add(object);
                }
                resultSet.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return list;
    }


    public static<T> List<T> findPreparedBySql(Object[] strs,String sql, DbConnection connection,Class<T> beanClass, List<String> fieldList, Map<String, Field> fieldMap) throws SQLException {
        PreparedStatement pstat = connection.getStatement(sql);
        if (strs != null && strs.length > 0) {
            for (int i = 1 ; i <= strs.length ; i++) {
                pstat.setObject(i, strs[i-1]);
                System.out.println("第"+i+"个参数值："+strs[i-1]);
            }
        }
        ResultSet resultSet = pstat.executeQuery();
        List<T> list = new ArrayList<T>();
        if(resultSet != null) {
            try {
                while(resultSet.next()){
                    T object = generateObject(beanClass,fieldList,fieldMap,resultSet);
                    list.add(object);
                }
                resultSet.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return list;
    }


    /**
     * 将数据库中的数据映射为实体对象
     * @param beanClass
     * @param fieldList
     * @param fieldMap
     * @param rs
     * @param <T>
     * @return
     * @throws Exception
     */
    public static<T> T generateObject(Class<T> beanClass, List<String> fieldList, Map<String, Field> fieldMap, ResultSet rs) throws Exception {
        T object = (T) beanClass.newInstance();
        for (String key : fieldList) {
            Field filed = fieldMap.get(key);
            Class<?> parameterType = filed.getType();
            if (String.class.equals(parameterType)) {
                filed.set(object, rs.getString(key));
            } else if (boolean.class.equals(parameterType) || Boolean.class.equals(parameterType)) {
                filed.set(object, rs.getBoolean(key));
            } else if (int.class.equals(parameterType) || Integer.class.equals(parameterType)) {
                filed.set(object, rs.getInt(key));
            } else if (float.class.equals(parameterType) || Float.class.equals(parameterType)) {
                filed.set(object, rs.getFloat(key));
            } else if (Date.class.equals(parameterType)) {
                filed.set(object, rs.getTimestamp(key));
            }
        }
        return object;
    }


    /**
     * 获取表中的字段
     * @param beanClass
     * @param <T>
     * @return
     */
    public static<T> String getTableColumn(Class<T> beanClass) {
        String tableColumn = "";
        for(Field field : beanClass.getDeclaredFields()) {
            if ("".equals(tableColumn)) {
                if (field.getAnnotation(ID.class) != null) {
                    tableColumn += field.getAnnotation(ID.class).value();
                } else {
                    if (field.getAnnotation(Column.class) != null) {
                        tableColumn += field.getAnnotation(Column.class).value();
                    }
                }
            } else {
                if (field.getAnnotation(Column.class) != null) {
                    tableColumn += "," + field.getAnnotation(Column.class).value();
                }
            }
        }
        return tableColumn;
    }


    /**
     * 获取主键字段
     * @param beanClass
     * @param <T>
     * @return list集合 固定为两个值 当只有一个主键时两个值一样
     */
    public static<T> List<Object> getIds(Class<T> beanClass) {
        List<Object> list = new ArrayList<>();
        Field[] fields = beanClass.getDeclaredFields();
        Object id1 = null;
        Object id2 = null;
        for (Field field : fields) {
            String propertyName;
            if (field.isAnnotationPresent(ID.class)) {
                propertyName = field.getAnnotation(ID.class).value();
                if (id1 == null || "".equals(id1)) {
                    id1 = propertyName;
                    id2 = propertyName;
                } else {
                    id2 = propertyName;
                }
            }
            field.setAccessible(true);
        }
        list.add(id1);
        list.add(id2);
        return list;
    }

    /**
     * 获取字段名map集合
     * @param beanClass
     * @param <T>
     * @return
     */
    public static<T> Map<String, Field> getFieldMap(Class<T> beanClass) {
        Map<String, Field> fieldMap = new HashMap<String, Field>();
        Field[] fields = beanClass.getDeclaredFields();
        for (Field field : fields) {
            String propertyName = null;
            if (field.isAnnotationPresent(Column.class)) {
                propertyName = field.getAnnotation(Column.class).value();
            } else if (field.isAnnotationPresent(ID.class)) {
                propertyName = field.getAnnotation(ID.class).value();
            }
            if (propertyName != null) {
                fieldMap.put(propertyName, field);
            }
            field.setAccessible(true);
        }
        return fieldMap;
    }


    /**
     * 获取字段名集合
     * @param beanClass
     * @param <T>
     * @return
     */
    public static<T> List<String> getFieldList(Class<T> beanClass) {
        List<String> fieldList = new ArrayList<>();
        Field[] fields = beanClass.getDeclaredFields();
        for (Field field : fields) {
            String propertyName = null;
            if (field.isAnnotationPresent(Column.class)) {
                propertyName = field.getAnnotation(Column.class).value();
            } else if (field.isAnnotationPresent(ID.class)) {
                propertyName = field.getAnnotation(ID.class).value();
            }
            if (propertyName != null) {
                fieldList.add(propertyName);
            }
            field.setAccessible(true);
        }
        return fieldList;
    }

}
